package gate

import (
	"fmt"
	"fruit/actor/iactor"
	"fruit/lib"
	"fruit/net/tcp"
	"fruit/tools/proto/proto_out"
	"fruit/tools/proto/proto_out/base"
	"fruit/tools/proto/proto_out/gate"
	"net"
	"sync"

	"google.golang.org/protobuf/proto"
)

type GateTcpConn struct {
	index int32
	conn  net.Conn
	uid   string
}

type GateServer struct {
	*iactor.Actor
	tcp_server      *tcp.TcpServer
	chan_conn       chan net.Conn
	chan_conn_close chan *GateTcpConn
}

var once sync.Once
var fruit_actor *GateServer

func GetGateServer() *GateServer {
	once.Do(func() {
		fruit_actor = new(GateServer)
		// fruit_actor.init()
	})
	return fruit_actor
}

func (my *GateServer) InitIActor(...interface{}) interface{} {
	//	tcp监听
	my.tcp_server = tcp.Listen("127.0.0.1:8889", my.on_tcp_conn)
	my.chan_conn = make(chan net.Conn, 100)
	my.chan_conn_close = make(chan *GateTcpConn, 100)
	// fmt.Println("建立tcp监听 8889")
	lib.RunGoroutine(my, "tcp_conn", tcp_conn)

	// in := &logic.TestReq{}
	// out := &logic.TestResp{}
	// lib.Call(lib.GetServiceId("logic"), proto_out.ProtoFuncEnum_Test3, in, out)

	// to := lib.GetServiceId("logic")
	// fmt.Println("succ Test3", to, lib.Ping(to))
	return nil
}

func (my *GateServer) OnClientGetTargetId([]byte) proto.Message {
	return nil
}

func (my *GateServer) on_tcp_conn(conn net.Conn) {
	my.chan_conn <- conn
}

func (my *GateServer) on_tcp_close(gate_conn *GateTcpConn) {
	my.chan_conn_close <- gate_conn
}

func tcp_conn(service iactor.IActor, args ...interface{}) {
	gate := service.(*GateServer)
	if gate.tcp_server != nil {
		// var map_conn map[int]net.Conn
		map_conn := make(map[int32]*GateTcpConn)
		var index int32 = 0
		for {
			select {
			case conn := <-gate.chan_conn:
				index++
				gate_conn := &GateTcpConn{
					index: index,
					conn:  conn,
				}
				map_conn[index] = gate_conn
				lib.RunGoroutine(gate, "tcp_recv", tcp_recv, gate_conn)

			case chan_close := <-gate.chan_conn_close:
				gate_conn, ex := map_conn[chan_close.index]
				if ex {
					tcp.CloseConn(gate_conn.conn)
					lib.Destory(gate_conn.uid)
					delete(map_conn, chan_close.index)
					fmt.Println("关闭 tcp_conn", chan_close.index)
				} else {
					fmt.Println("未找到 tcp_conn", chan_close.index)
				}
			}

			// // for i := 0; i < 1000; i++ {
			// // 	lib.GetServerInstance().Create("center.CenterUser", service.Uid(), cn)
			// // }
			// resp := lib.GetServerInstance().Call(uid, "Ping", center)
			// fmt.Printf("center第一次操作数据结果 %v\n", resp...)
			// // lib.GetServerInstance().Push(uid, "Ping2", service.Uid())
		}
	}
}

func tcp_recv(service iactor.IActor, args ...interface{}) {
	gate_conn := args[0].(*GateTcpConn)
	gate_service := service.(*GateServer)
	defer gate_service.on_tcp_close(gate_conn)
	msg := &base.GateUserInitReq{
		Index: gate_conn.index,
	}
	resp := lib.Create("gate.gateuser", msg)
	if resp != nil {
		gate_conn.uid = resp.Uid
		fmt.Println("收到tcp conn", gate_conn.index, resp.Uid, gate_conn.conn)

		bts := make([]byte, 1024*1024)
		msg := &gate.RecvDataReq{}
		// msg.Data = make([]byte, 1024*1024)

		for {
			len, err := gate_conn.conn.Read(bts)
			if err != nil {
				if err.Error() != "EOF" {
					fmt.Println("消息接收异常", err, len)
				}
				break
			}
			// fmt.Println("recv", msg.Data, len)
			msg.Data = make([]byte, len)
			copy(msg.Data, bts[:len])
			// msg.Data = bts[:len]
			lib.Push(gate_conn.uid, proto_out.ProtoFuncEnum_RecvTcpData, msg)
		}
	}

}
